#ifndef __safTools_h__
#define __safTools_h__

#pragma once

#ifndef __GNUC__
#ifndef __safTools_i_h__
_FK_BEGIN
	#include "fk\safTools_i.h"
_FK_END
#else
	#include "fk\safTools_i.h"
#endif
#endif // __GNUC__


#include "fk\WinCtrl.hxx"
#include "fk\CommandMode.hxx"
#include "fk\CommandItem.hxx"
#include "fk\CommandBars.hxx"
#include "fk\PopupMenuBarFK.hxx"

_FK_BEGIN

struct FK_LVCOLUMN : public LVCOLUMN
{
	DWORD dwSize;
	int nColumnKey;
	fk::IHeaderItem *pHeaderItem;
};


template<class _TWndClass>
class IDataViewImpl :	public ATL::IDispatchImpl<IDataView, &IID_IDataView>
{
private:
	LONG m_dwRef;

public:
	IDataViewImpl():
	  m_dwRef(0)
	  {
	  }

	  STDMETHODIMP QueryInterface(REFIID riid, void **ppv)
	  {
		  if((riid == IID_IUnknown) || (riid==IID_IDispatch) || (riid == IID_IDataView))
		  {
			  *ppv = (IUnknown*)this;

			  ((IUnknown*)*ppv)->AddRef();
			  return S_OK; 
		  }

		  *ppv = NULL;
		  return S_FALSE;
	  }

	  STDMETHODIMP_(ULONG) AddRef()
	  {
		  return InterlockedIncrement(&m_dwRef);
	  }

	  STDMETHODIMP_(ULONG) Release()
	  {
		  ULONG result = InterlockedDecrement(&m_dwRef);
		  if(result == 0)
			  delete this;
		  return result;
	  }
};

//
// IThumbnailInfoCommand
class CThumbnailInfoCommand : public fk::ICommand
{
public:
	CThumbnailInfoCommand(fk::LObject* powner):
	 fk::ICommand(powner)
	{
	}
	virtual ~CThumbnailInfoCommand()
	{
	}

	void virtual SetCommandName(BSTR *bstrName)
	{
		*bstrName = ::SysAllocString(L"Thumbnail");
	}

	virtual int Execute()
	{
		return S_OK;
	}

	void virtual Command_Undo()
	{

	}

	void virtual Command_Describe(BSTR *bstrName)
	{
		*bstrName = ::SysAllocString(L"Describe");
	}

protected:
private:
};


/////////////////////////////////////////////////////////////////////////
// class CAutoThreadNotify
class CAutoThreadNotify
{
public:
	CAutoThreadNotify(IThreadNotify *pThreadNotify, int nThreadID, bool bRun);
	~CAutoThreadNotify();

	void ThreadNotify_Begin();
	void ThreadNotify_End();

protected:
	IThreadNotify	*m_pThreadNotify;
	bool m_bRun;
	int m_nThreadID;

private:
};

inline CAutoThreadNotify::CAutoThreadNotify(IThreadNotify *pThreadNotify, int nThreadID, bool bRun)
:m_pThreadNotify( pThreadNotify ),
m_bRun( bRun ),
m_nThreadID( nThreadID )
{
	if(m_bRun)
	{
		ThreadNotify_Begin();
	}
}

inline CAutoThreadNotify::~CAutoThreadNotify()
{
	if(m_bRun)
	{
		ThreadNotify_End();
	}
}

inline void CAutoThreadNotify::ThreadNotify_Begin()
{
	if(m_pThreadNotify!=NULL)
	{
		m_pThreadNotify->ThreadNotify_Begin();
	}
}

inline void CAutoThreadNotify::ThreadNotify_End()
{
	if(m_pThreadNotify!=NULL)
	{
		m_pThreadNotify->ThreadNotify_Begin();
	}
}

// class CAutoIThreadNotifys
class CAutoIThreadNotifys
{
public:
	CAutoIThreadNotifys::CAutoIThreadNotifys(IThreadNotifys *pThreadNotifys, int nThreadID, bool bRun)
		:m_pThreadNotifys( pThreadNotifys ),
		m_bRun( bRun ),
		m_nThreadID( nThreadID )
	{
		if(m_bRun)
		{
			ThreadNotify_Begin();
		}
	}

	CAutoIThreadNotifys::~CAutoIThreadNotifys()
	{
		if(m_bRun)
		{
			ThreadNotify_End();
		}
	}

	void CAutoIThreadNotifys::ThreadNotify_Begin()
	{
		if(m_pThreadNotifys!=NULL)
		{
			m_pThreadNotifys->ThreadNotify_Begin();
		}
	}

	void CAutoIThreadNotifys::ThreadNotify_End()
	{
		if(m_pThreadNotifys!=NULL)
		{
			m_pThreadNotifys->ThreadNotify_End();
		}
	}

protected:
	IThreadNotifys	*m_pThreadNotifys;
	bool m_bRun;
	int m_nThreadID;
private:
};


class CAutoProgressWait
{
public:
	CAutoProgressWait(IProgressWait *pProgressWait, int nProgress, bool bRun):
	  m_pProgressWait(pProgressWait),
		  m_bRun(bRun)
	  {
		  if(m_bRun)
		  {
			  this->ProgressWait_Begin();
		  }
	  }
	  ~CAutoProgressWait()
	  {
		  if(m_bRun)
		  {
			  this->ProgressWait_End();
		  }
	  }
	  void ProgressWait_Begin( void )
	  {
		  if(m_pProgressWait!=NULL)
		  {
			  this->m_pProgressWait->ProgressWait_Begin( m_nProgress );
		  }
	  }

	  void ProgressWait_End( void )
	  {
		  if(m_pProgressWait!=NULL)
		  {
			  this->m_pProgressWait->ProgressWait_End( m_nProgress );
		  }
	  }

protected:
	IProgressWait *m_pProgressWait;
	bool m_bRun;
	int m_nProgress;

private:
};



class CInitSafTools
{
public:
	void fmToolsStartup()
	{
		fk::fmToolsStartup(&m_token);
	}

	void fmToolsShutdown()
	{
		fk::fmToolsShutdown(&m_token);
	}

protected:
	ULONG_PTR m_token;
};


_FK_END



_FK_BEGIN

#ifndef __FK_INTOOLS_H__
	#pragma comment(lib, "SafTools.lib")
#endif	// __FK_INTOOLS_H__

_FK_END


#endif // __safTools_h__
